#pragma once
#include <vector>
#include <algorithm>
using namespace std;
#include "point.h"
#include <Eigen/Sparse>
#include <Eigen/SparseLU>
#include <Eigen/PardisoSupport>

enum BASIS_TYPE//basis function type
{
	TWO_DIM_LINEAR,//2D linear
	TWO_DIM_QUADRATIC,//2D quadratic
	TWO_DIM_BILINEAR,//2D bilinear
	TWO_DIM_BIQUADRATIC//2D biquadratic
};

enum BOUNDARY_TYPE//boundary type
{
	Dirichlet,
	Neumann,
	Robin,
	Other
};



enum ELE_TYPE {//finite element type
	ELE_3 = 3,//Linear triangle element with 3 nodes
	ELE_4 = 4,//Bilinear element with 4 nodes
	ELE_6 = 6,//quadratic triangle element with 6 nodes
	ELE_9 = 9//Biquadratic element with 9 nodes
};

enum SOLVE_METHOD {
	DIREC_SparseLU,
	DIREC_SimplicialCholesky,
	DIREC_PardisoLU,
	DIREC_PardisoLDLT,
	ITERA_ConjugateGradient,

};

//One node for boundary
struct boundary_node
{
	BOUNDARY_TYPE type;//define the boundary type
	int glo_node_index;//define the global index of the boundary node
	double(*value)(CPoint,double t);//define the boundary value, it can be very complex and define by a function
	CPoint outer_normal_vector;//outer normal vector of the boundary used by Robin and Neumann conditions
};

//One edge for boundary
struct boundary_edge
{
	BOUNDARY_TYPE type;//type of the boundary edge
	int ele_index;// the index of the element which contains the boundary edge
	pair<int,int> p;//the global node of the boundary edge
	double(*value)(CPoint,double t) ;//define the boundary value of Neumann or Robin, it is defined by a function
	double(*r)(CPoint,double t);//define the coefficient before the Dirichlet condition

	boundary_edge(int e, pair<int,int>p0) { ele_index = e, p = p0; }//construct function for boundary_edge
	boundary_edge() {};
};

typedef Eigen::SparseMatrix<double> SpMat;//declares a sparse matrix type of double
typedef Eigen::VectorXd Rsv;//declares a right side value type
typedef Eigen::Triplet<double> Tri;//declares a triplet to stores the matrix index and values, then convert it to sparse matrix(with high performance)
typedef Eigen::PardisoLU   <SpMat > PLUSolver;
typedef Eigen::PardisoLDLT <SpMat> PLDLTSolver;
